package com.ly.mp.busicen.rule.instrumentation.plugin;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.stereotype.Component;

import com.ly.mp.busicen.rule.flow.IDataVolume;
import com.ly.mp.busicen.rule.flow.IFlowContext;
import com.ly.mp.busicen.rule.flow.IFlowResult;
import com.ly.mp.busicen.rule.flow.IFlowResultCtn;
import com.ly.mp.busicen.rule.flow.IFlowResultCtn.Risultato;
import com.ly.mp.busicen.rule.flow.IFlowVolume;
import com.ly.mp.busicen.rule.flow.action.IAction;
import com.ly.mp.busicen.rule.flow.action.IActionResult;
import com.ly.mp.busicen.rule.flow.action.IActionResult.Signal;
import com.ly.mp.busicen.rule.flow.filter.FlowFilter;
import com.ly.mp.busicen.rule.flow.filter.FlowInvocation;
import com.ly.mp.busicen.rule.flow.filter.FlowResult;
import com.ly.mp.busicen.rule.instrumentation.IFlowInstrumentation;
import com.ly.mp.busicen.rule.log.RuleLogData;
import com.ly.mp.busicen.rule.log.RuleLogData.RuleLogType;
import com.ly.mp.busicen.rule.log.RuleLogPublisher;
import com.ly.mp.busicen.rule.log.RuleLogState;

/**
 * 揭露日志
 * 
 * @author ly-liuweisong
 *
 */
@Component
public class LogInstrumentation implements IFlowInstrumentation {

	Map<String, RuleLogPublisher> logPublisher = new ConcurrentHashMap<>();

	final static String EMPTYSTR = "";

	RuleLogState flowState2LogState(Signal signal) {
		switch (signal) {
		case BREAK:
			return RuleLogState.BREAK;
		case EXCPT:
			return RuleLogState.EXCPT;
		default:
			return RuleLogState.END;
		}
	}

	@Override
	public void beginFlow(String flow, String brand, Map<String, Object> data, String rid) {
		RuleLogPublisher ruleLogPublisher = new RuleLogPublisher();
		logPublisher.put(rid, ruleLogPublisher);
		ruleLogPublisher
				.log(RuleLogData.create(rid, flow, "FLOWSTART", RuleLogType.FLOW, RuleLogState.START, EMPTYSTR, null, data));
	}

	@Override
	public void endBuildContext(IFlowContext context) {

	}

	@Override
	public void beginActionInvoke(IAction action, IFlowContext context, IFlowResultCtn result) {
		logPublisher.get(context.flowVolume().rid())
				.log(RuleLogData.create(context.flowVolume().rid(), context.flowVolume().flow(), action.action(),
						RuleLogType.ACTION, RuleLogState.START, EMPTYSTR, null, context.dataVolume()));
	}

	@Override
	public void endActionInvoke(IAction action, IFlowContext context, IFlowResultCtn result, IFlowResult flowResult) {
		logPublisher.get(context.flowVolume().rid())
				.log(RuleLogData.create(context.flowVolume().rid(), context.flowVolume().flow(), action.action(),
						RuleLogType.ACTION, flowState2LogState(flowResult.signal()), EMPTYSTR, result.excpt(),
						context.dataVolume()));
	}

	@Override
	public void beginFilter(FlowFilter flowFilter, FlowInvocation invocation) {
		logPublisher.get(invocation.flowVolume().rid())
				.log(RuleLogData.create(invocation.flowVolume().rid(), invocation.flowVolume().flow(),
						flowFilter.fileterName(), RuleLogType.FILTER, RuleLogState.START, EMPTYSTR, null,
						invocation.dataVolume()));
	}

	@Override
	public void endFilter(FlowFilter flowFilter, FlowInvocation invocation, FlowResult filterResult) {
		logPublisher.get(invocation.flowVolume().rid())
		.log(RuleLogData.create(invocation.flowVolume().rid(), invocation.flowVolume().flow(),
				flowFilter.fileterName(), RuleLogType.FILTER, flowState2LogState(filterResult.actionResult().signal()), EMPTYSTR, filterResult.actionResult().excpt(),
				invocation.dataVolume()));
	}

	@Override
	public void beginActionExecute(IAction action, IDataVolume dataVolume, IFlowVolume flowVolume) {
		logPublisher.get(flowVolume.rid())
		.log(RuleLogData.create(flowVolume.rid(), flowVolume.flow(), action.action(),
				RuleLogType.RULE, RuleLogState.START, EMPTYSTR, null, dataVolume));
	}

	@Override
	public void endActionExecute(IAction action, IDataVolume dataVolume, IFlowVolume flowVolume,
			IActionResult actionResult) {
		logPublisher.get(flowVolume.rid())
		.log(RuleLogData.create(flowVolume.rid(), flowVolume.flow(), action.action(),
				RuleLogType.RULE, flowState2LogState(actionResult.signal()), EMPTYSTR, actionResult.excpt(), dataVolume));
	}

	@Override
	public void endFlow(IFlowResultCtn result) {
		RuleLogState state ;//=result.risultato();// == Risultato.FINISH ? RuleLogState.END : RuleLogState.EXCPT;
		if (result.risultato() == Risultato.FINISH) {
			state = RuleLogState.END;
		}else if(result.risultato() == Risultato.BREAK) {
			state = RuleLogState.BREAK;
		}else {
			state = RuleLogState.EXCPT;
		}
		Object data = result.risultato() == Risultato.FINISH ? result.exitResult() : result.flowContext().dataVolume();
		String msg = "";
		if (result.risultato() == Risultato.BREAK) {
			msg = result.breakResult().actionName();
		} else if (result.risultato() == Risultato.EXCPT) {
			msg = "执行异常";
		}
		logPublisher.get(result.flowContext().flowVolume().rid())
				.log(RuleLogData.create(result.flowContext().flowVolume().rid(),
						result.flowContext().flowVolume().flow(), "FLOWEND", RuleLogType.FLOW, state, msg,
						result.excpt(), data));
		logPublisher.remove(result.flowContext().flowVolume().rid());
	}

	@Override
	public String label() {
		return "metrics";
	}

}
